package org.gavin.core.service.limit.impl;

import com.github.benmanes.caffeine.cache.Cache;
import org.gavin.core.annotation.AccessLimit;
import org.gavin.core.domain.ExpireCache;
import org.gavin.core.entity.AutoExpire;
import org.gavin.core.service.limit.AccessLimitAbstract;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * YmlAccessLimit
 *
 * @author grl
 * @date 2024/1/24
 */
public class LocalAccessLimit implements AccessLimitAbstract {

    private final Cache<String, AutoExpire> cache;

    public LocalAccessLimit(Cache<String, ? extends ExpireCache> cache) {
        this.cache = (Cache<String, AutoExpire>) cache;
    }

    @Override
    public boolean accessDenied(AccessLimit limit, String method, Object[] args) {
        AutoExpire<AtomicInteger> autoExpire = getAndLoader(method, limit);
        return autoExpire.getData().getAndIncrement() > limit.count();
    }

    private AutoExpire<AtomicInteger> getAndLoader(String key, AccessLimit limit) {
        return cache.get(key, str -> {
            AutoExpire<AtomicInteger> autoExpire = new AutoExpire<>();
            autoExpire.setExpireTime(limit.period());
            autoExpire.setData(new AtomicInteger(1));
            return autoExpire;
        });
    }
}
